# coding: utf-8
from enum import Enum
from pathlib import Path
from typing import Union
from abc import ABC, abstractmethod

from PySide6.QtCore import QFile, QFileDevice
import json


class FileBase(Enum):
    """
    文件类型枚举
    """

    @abstractmethod
    def path(self) -> str:
        """
        获取文件路径
        :return: 文件路径
        """
        raise NotImplementedError


class QFileManager:
    """
    文件管理类
    """

    def __init__(
            self,
            file_name: Union[str, Path, FileBase],
            mode: str = "r",
            encoding: str = "utf-8"
    ):
        """
        初始化文件管理类
        :param file_name: 文件路径
        :param mode: 文件打开模式
                r: 读模式
                w: 写模式
                a: 追加模式
                x: 创建模式
                b: 二进制模式
                t: 文本模式
                +: 读写模式
        :param encoding: 文件编码
        """
        if isinstance(file_name, FileBase):
            file_name = file_name.path()
        self.file = QFile(file_name)
        self.encoding = encoding

        if mode == "r":
            self.file.open(QFile.OpenModeFlag.ReadOnly)
        elif mode == "w":
            self.file.open(QFile.OpenModeFlag.WriteOnly)
        elif mode == "a":
            self.file.open(QFile.OpenModeFlag.Append)
        elif mode == "x":
            self.file.open(QFile.OpenModeFlag.WriteOnly | QFile.OpenModeFlag.Text | QFile.OpenModeFlag.NewOnly)
        elif mode == "b":
            self.file.open(QFile.OpenModeFlag.ReadOnly | QFile.OpenModeFlag.Unbuffered)
        elif mode == "t":
            self.file.open(QFile.OpenModeFlag.ReadOnly | QFile.OpenModeFlag.Text)
        elif mode == "w+":
            self.file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Truncate)
        elif mode == "a+":
            self.file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Text | QFile.OpenModeFlag.Append)
        elif mode == "x+":
            self.file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Text | QFile.OpenModeFlag.NewOnly)
        elif mode == "b+":
            self.file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Unbuffered)
        elif mode == "t+":
            self.file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Text)
        else:
            raise ValueError("Invalid mode")

    def read(self, size: int = -1) -> str:
        """
        读取文件内容
        :return: 文件内容
        """
        return self.file.read(size).data().decode(self.encoding)

    def read_all(self) -> str:
        """
        读取文件内容
        :return: 文件内容
        """
        return self.read_bytes().decode(self.encoding)

    def write(self, content: str) -> None:
        """
        写入文件内容
        :param content: 文件内容
        """
        self.write_bytes(content.encode(self.encoding))

    def read_bytes(self) -> bytes:
        """
        读取文件内容
        :return: 文件内容
        """
        return self.file.readAll().data()

    def write_bytes(self, content: bytes) -> None:
        """
        写入文件内容
        :param content: 文件内容
        """
        self.file.write(content)

    def close(self) -> None:
        """
        关闭文件
        """
        self.file.close()

    def is_open(self) -> bool:
        """
        判断文件是否打开
        :return: 是否打开
        """
        return self.file.isOpen()

    def is_exists(self) -> bool:
        """
        判断文件是否存在
        :return:
        """
        return self.file.exists()

    def remove(self) -> None:
        """
        删除文件
        """
        self.file.remove()
        self.close()

    def rename(self, new_file_path: str) -> None:
        """
        重命名文件
        :param new_file_path: 新文件路径
        """
        self.file.rename(new_file_path)

    def size(self) -> int:
        """
        获取文件大小
        :return: 文件大小
        """
        return self.file.size()

    def set_file_name(self, file_name: str) -> None:
        """
        设置文件路径
        :param file_name: 文件路径
        """
        self.file.setFileName(file_name)

    def file_name(self) -> str:
        """
        获取文件路径
        :return: 文件路径
        """
        return self.file.fileName()

    def set_permissions(self, permissions: QFileDevice.Permission) -> None:
        """
        设置文件权限
        :param permissions: 权限值
        """
        self.file.setPermissions(permissions)

    def permissions(self) -> QFileDevice.Permission:
        """
        获取文件权限
        :return: 权限值
        """
        return self.file.permissions()

    def read_json(self) -> dict:
        """
        读取json文件内容
        :return: json内容
        """
        return json.loads(self.read_all())

    def peek(self, size: int = -1) -> str:
        """
        预览文件内容
        :param size:
        :return:
        """
        return str(self.file.peek(size).data(), self.encoding)

    def peek_bytes(self, size: int = -1) -> bytes:
        """
        预览文件内容
        :param size:
        :return:
        """
        return self.file.peek(size).data()

    def pos(self) -> int:
        """
        获取文件指针位置
        :return:
        """
        return self.file.pos()

    def __enter__(self):
        """
        进入with语句块
        :return: 文件管理类实例
        """
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        退出with语句块
        :param exc_type: 异常类型
        :param exc_val: 异常值
        :param exc_tb: 异常追踪信息
        """
        self.close()

    def __del__(self):
        self.close()

    def __repr__(self):
        return f"QFileManager({self.file.fileName()})"

    def __str__(self):
        return f"QFileManager({self.file.fileName()})"
